
#ifndef _OSCDOCUMENT_H_
#define _OSCDOCUMENT_H_

#include <BMap>
#include <BScene>
#include <BMesh>
#include <BGeometry>
#include <BCone>
#include <BCube>
#include <BCylinder>
#include <BSphere>
#include <BGeoSphere>
#include <BTube>
#include <BTorus>
#include <BSurface>
#include <BTerrain>
#include <BBillboard>
#include <BTextual>
#include <BParticle>
#include <BPhysics>

#include <BFont>
#include <BImage>
#include <BStyle>
#include <BPixmap>
#include <BMaterial>
#include <BProgram>
#include <BUniform>
#include <BFile>
#include <BSpring>
#include <BSpacer>
#include <BScript>
#include <BSource>
#include <BClass>

#include <BReadWrite>
#include <BSonDocument>

using namespace BWE;

class SonFormat
{
public:
	SonFormat(const BString& text)
	{
		head_prev = 0;
		head_post = 0;
		tail_prev = 0;
		tail_post = 0;
		equal_prev = 0;
		equal_post = 0;
		end_post = 0;

		int head_pos = text.find('{');
		if (head_pos < text.size())
		{
			head_prev = text(head_pos - 1);
			head_post = text(head_pos + 1);
		}

		int tail_pos = text.find('}');
		if (tail_pos < text.size())
		{
			tail_prev = text(tail_pos - 1);
			tail_post = text(tail_pos + 1);
		}

		int equal_pos = text.find('=');
		if (equal_pos < text.size())
		{
			equal_prev = text(equal_pos - 1);
			equal_post = text(equal_pos + 1);
		}

		int end_pos = text.find(';');
		if (end_pos < text.size())
		{
			end_post = text(end_pos + 1);
		}

		if (head_prev && !isspace(head_prev))
			head_prev = 0;
		if (head_post && !isspace(head_post))
			head_post = 0;
		if (tail_prev && !isspace(tail_prev))
			tail_prev = 0;
		if (tail_post && !isspace(tail_post))
			tail_post = 0;
		if (equal_prev && !isspace(equal_prev))
			equal_prev = 0;
		if (equal_post && !isspace(equal_post))
			equal_post = 0;
		if (end_post && !isspace(end_post))
			end_post = 0;
	}

	char		head_prev;
	char		head_post;
	char		tail_prev;
	char		tail_post;
	char		equal_prev;
	char		equal_post;
	char		end_post;
};

class OscDocument : public BObject
{
	BOBJECT(OscDocument)
public:
	OscDocument();
	~OscDocument();

	bool setFormat(const BString& format);
	const BString& format() const;

	BObject* load(const BString& fileName);
	BObject* read(const BStream& stream);

	bool load(const BString& fileName, BObject* object);
	bool save(const BString& fileName, const BObject* object) const;

	bool read(const BStream& stream, BObject* object);
	bool write(BStream& stream, const BObject* object) const;

protected:
	BObject* readObject(const BSonNode* node);

	bool readObjectData(const BSonNode* son, BObject* object);
	bool readShapeData(const BSonNode* son, BShape* shape);
	bool readNodeData(const BSonNode* son, BNode* node);
	bool readTextureData(const BSonNode* son, BTexture* texture);

	bool readScene(const BSonNode* son, BScene* scene);
	bool readNode(const BSonNode* son, BNode* node);
	bool readLight(const BSonNode* son, BLight* light);
	bool readCamera(const BSonNode* son, BCamera* camera);
	bool readBillboard(const BSonNode* son, BBillboard* billboard);
	bool readGroup(const BSonNode* son, BGroup* group);

	bool readMesh(const BSonNode* son, BMesh* mesh);
	bool readGeometry(const BSonNode* son, BGeometry* geometry);
	bool readTextual(const BSonNode* son, BTextual* textual);
	bool readParticle(const BSonNode* son, BParticle* particle);
	bool readElement(const BSonNode* son, BElement* element);

	bool readCube(const BSonNode* son, BCube* cube);
	bool readCone(const BSonNode* son, BCone* cone);
	bool readCylinder(const BSonNode* son, BCylinder* cylinder);
	bool readSphere(const BSonNode* son, BSphere* sphere);
	bool readGeoSphere(const BSonNode* son, BGeoSphere* geoSphere);
	bool readTube(const BSonNode* son, BTube* tube);
	bool readTorus(const BSonNode* son, BTorus* torus);
	bool readSurface(const BSonNode* son, BSurface* surface);
	bool readTerrain(const BSonNode* son, BTerrain* terrain);

	bool readMaterial(const BSonNode* son, BMaterial* material);
	bool readImage(const BSonNode* son, BImage* image);
	bool readPixmap(const BSonNode* son, BPixmap* pixmap);
	bool readProgram(const BSonNode* son, BProgram* program);
	bool readShader(const BSonNode* son, BShader* shader);
	bool readUniform(const BSonNode* son, BUniform* uniform);
	bool readScript(const BSonNode* son, BScript* script);

	bool readScriptExp(const BSonNode* son, BExp* exp);
	bool readVectorArray(const BSonNode* son, BVectorArray* vertices);
	bool readCoordArray(const BSonNode* son, BCoordArray* coords);
	bool readColorArray(const BSonNode* son, BColorArray* colors);
	bool readFaceArray(const BSonNode* son, BFaceArray* faces);
	bool readIndexArray(const BSonNode* son, BIndexArray* indices);
	bool readPieceArray(const BSonNode* son, BPieceArray* pieces);
	bool readScalarTable(const BSonNode* son, BRealTable& ftable);
	bool readByteArray(const BSonNode* son, BByteArray* bytes);

public:
	BSonNode* writeObject(const BObject* object) const;

	bool writeObjectData(BSonNode* son, const BObject* object);
	bool writeNodeData(BSonNode* son, const BNode* node);
	bool writeShapeData(BSonNode* son, const BShape* shape);
	bool writeTextureData(BSonNode* son, const BTexture* texture);

	bool writeScene(BSonNode* son, const BScene* scene);
	bool writeNode(BSonNode* son, const BNode* node);
	bool writeLight(BSonNode* son, const BLight* light);
	bool writeCamera(BSonNode* son, const BCamera* camera);
	bool writeGroup(BSonNode* son, const BGroup* group);

	bool writeMesh(BSonNode* son, const BMesh* mesh);
	bool writeGeometry(BSonNode* son, const BGeometry* geometry);
	bool writeBillboard(BSonNode* son, const BBillboard* billboard);
	bool writeTextual(BSonNode* son, const BTextual* textual);
	bool writeParticle(BSonNode* son, const BParticle* particle);
	bool writeElement(BSonNode* son, const BElement* element);

	bool writeCube(BSonNode* son, const BCube* cube);
	bool writeCone(BSonNode* son, const BCone* cone);
	bool writeCylinder(BSonNode* son, const BCylinder* cylinder);
	bool writeSphere(BSonNode* son, const BSphere* sphere);
	bool writeGeoSphere(BSonNode* son, const BGeoSphere* geoSphere);
	bool writeTube(BSonNode* son, const BTube* tube);
	bool writeTorus(BSonNode* son, const BTorus* torus);
	bool writeSurface(BSonNode* son, const BSurface* surface);
	bool writeTerrain(BSonNode* son, const BTerrain* terrain);

	bool writeMaterial(BSonNode* son, const BMaterial* material);
	bool writeImage(BSonNode* son, const BImage* image);
	bool writePixmap(BSonNode* son, const BPixmap* pixmap);
	bool writeProgram(BSonNode* son, const BProgram* program);
	bool writeShader(BSonNode* son, const BShader* shader);
	bool writeUniform(BSonNode* son, const BUniform* uniform);
	bool writeScript(BSonNode* son, const BScript* script);

	bool writeScriptExp(BSonNode* son, const BExp* exp);
	bool writeVectorArray(BSonNode* son, const BVectorArray* vertices);
	bool writeCoordArray(BSonNode* son, const BCoordArray* coords);
	bool writeColorArray(BSonNode* son, const BColorArray* colors);
	bool writeFaceArray(BSonNode* son, const BFaceArray* faces);
	bool writeFloatTable(BSonNode* son, const BFloatTable& ftable);
	bool writeIndexArray(BSonNode* son, const BIndexArray* indices, int group);
	bool writePieceArray(BSonNode* son, const BPieceArray* pieces, int group);
	bool writeByteArray(BSonNode* son, const BByteArray* bytes, int group);

private:
	inline const char* stringOfBool(bool v)
	{
		if (v)
			return "true";
		return "false";
	}
	inline const BString& stringOfVector(const BVector& vec)
	{
		_text.reset();
		_text << vec.x() << ',' << vec.y() << ',' << vec.z();
		return _text;
	}
	inline const BString& stringOfCoord(const BCoord& coord)
	{
		_text.reset();
		_text << coord.x() << ',' << coord.y();
		return _text;
	}
	inline const BString& stringOfQuater(const BQuater& quater)
	{
		_text.reset();
		_text << quater.x() << ',' << quater.y() << ',' << quater.z() << ',' << quater.w();
		return _text;
	}
	inline const BString& stringOfColor(const BColor& color)
	{
		_text.reset();
		_text << color.r() << ',' << color.g() << ',' << color.b() << ',' << color.a();
		return _text;
	}
	inline const BString& stringOfSize(const BSize& size)
	{
		_text.reset();
		_text << size.width() << ',' << size.height();
		return _text;
	}
	inline const BString& stringOfQuad(const BQuad& quad)
	{
		_text.reset();
		const BVector& a = quad.a();
		const BVector& b = quad.b();
		const BVector& c = quad.c();
		const BVector& d = quad.d();
		_text << a.x() << ',' << a.y() << ',' << a.z() << ',';
		_text << b.x() << ',' << b.y() << ',' << b.z() << ',';
		_text << c.x() << ',' << c.y() << ',' << c.z() << ',';
		_text << d.x() << ',' << d.y() << ',' << d.z();
		return _text;
	}
	inline const BString& stringOfFont(const BFont* font)
	{
		_text.reset();
		_text << font->family() << ',' << font->size();
		return _text;
	}
	inline const BString& stringOfAlign(Align align)
	{
		_text.reset();
		if (align & Align_Left)
			_text << "left" << ',';
		if (align & Align_Top)
			_text << "top" << ',';
		if (align & Align_Right)
			_text << "right" << ',';
		if (align & Align_Bottom)
			_text << "bottom" << ',';
		if (align & Align_HCenter)
			_text << "hcenter" << ',';
		if (align & Align_VCenter)
			_text << "vcenter" << ',';
		if (_text.size())
			_text -= ',';
		return _text;
	}
	inline const BString& stringOfFormat(Format format)
	{
		_text.reset();
		switch (format)
		{
		case BWE::Format_Char:
			_text << "char";
			break;
		case BWE::Format_UChar:
			_text << "uchar";
			break;
		case BWE::Format_Short:
			_text << "short";
			break;
		case BWE::Format_UShort:
			_text << "ushort";
			break;
		case BWE::Format_Int:
			_text << "int";
			break;
		case BWE::Format_UInt:
			_text << "uint";
			break;
		case BWE::Format_Float:
			_text << "float";
			break;
		case BWE::Format_Double:
			_text << "double";
			break;
		case BWE::Format_RGB:
			_text << "rgb";
			break;
		case BWE::Format_RGBA:
			_text << "rgba";
			break;
		case BWE::Format_Gray:
			_text << "gray";
			break;
		case BWE::Format_Gray_Alpha:
			_text << "gray-alpha";
			break;
		case BWE::Format_Alpha:
			_text << "alpha";
			break;
		case BWE::Format_Compressed_RGB:
			_text << "compressed-rgb";
			break;
		case BWE::Format_Compressed_RGBA:
			_text << "compressed-rgba";
			break;
		case BWE::Format_Compressed_Gray:
			_text << "compressed-gray";
			break;
		case BWE::Format_Compressed_Gray_Alpha:
			_text << "compressed-gray-alpha";
			break;
		case BWE::Format_Compressed_Alpha:
			_text << "compressed-alpha";
			break;
		default:
			_text << "none";
			break;
		}
		return _text;
	}
	inline const BString& stringOfPolyMode(PolyMode polyMode)
	{
		_text.reset();
		switch (polyMode)
		{
		case Poly_Line:
			_text << "line";
			break;
		case Poly_Point:
			_text << "point";
			break;
		default:
			_text << "fill";
			break;
		}
		return _text;
	}
	inline const BString& stringOfBlend(BTexture::Blend blend)
	{
		_text.reset();
		switch (blend)
		{
		case BTexture::Blend_Modulate:
			_text << "modulate";
			break;
		case BTexture::Blend_Replace:
			_text << "replace";
			break;
		case BTexture::Blend_Decal:
			_text << "decal";
			break;
		case BTexture::Blend_Color:
			_text << "color";
		default:
			_text << "none";
			break;
		}
		return _text;
	}
	inline const BString& stringOfWrap(BTexture::Wrap wrap)
	{
		_text.reset();
		switch (wrap)
		{
		case BTexture::Wrap_Clamp:
			_text << "clamp";
			break;
		case BTexture::Wrap_Repeat:
			_text << "repeat";
			break;
		default:
			_text << "none";
			break;
		}
		return _text;
	}
	inline const BString& stringOfFilter(BTexture::Filter filter)
	{
		_text.reset();
		switch (filter)
		{
		case BTexture::Filter_Nearest:
			_text << "nearest";
			break;
		case BTexture::Filter_Linear:
			_text << "linear";
			break;
		default:
			_text << "none";
			break;
		}
		return _text;
	}
	inline const BString& stringOfLightType(BLight::Type type)
	{
		_text.reset();
		switch (type)
		{
		case BLight::Type_Point:
			_text << "point";
			break;
		case BLight::Type_Spot:
			_text << "spot";
			break;
		case BLight::Type_Direct:
			_text << "direct";
			break;
		}
		return _text;
	}
	inline const BString& stringOfPrimitive(Primitive primitive)
	{
		_text.reset();
		switch (primitive)
		{
		case Primitive_Points:
			_text << "points";
			break;
		case Primitive_Lines:
			_text << "lines";
			break;
		case Primitive_LineStrip:
			_text << "lineStrip";
			break;
		case Primitive_LineLoop:
			_text << "lineLoop";
			break;
		case Primitive_Triangles:
			_text << "triangles";
			break;
		case Primitive_TriangleStrip:
			_text << "triangleStrip";
			break;
		case Primitive_TriangleFan:
			_text << "triangleFan";
			break;
		case Primitive_Quads:
			_text << "quads";
			break;
		case Primitive_QuadStrip:
			_text << "quadStrip";
			break;
		case Primitive_Polygon:
			_text << "polygon";
			break;
		default:
			_text << "none";
			break;
		}
		return _text;
	}
	inline const BString& stringOfUniformType(BUniform::Type type)
	{
		_text.reset();
		switch (type)
		{
		case BUniform::Type_Int:
			_text << "int";
			break;
		case BUniform::Type_UInt:
			_text << "uint";
			break;
		case BUniform::Type_Float:
			_text << "float";
			break;
		case BUniform::Type_Double:
			_text << "double";
			break;
		case BUniform::Type_Vec3f:
			_text << "vec3f";
			break;
		case BUniform::Type_Vec4f:
			_text << "vec4f";
			break;
		case BUniform::Type_Vec3d:
			_text << "vec3d";
			break;
		case BUniform::Type_Vec4d:
			_text << "vec4d";
			break;
		case BUniform::Type_Matrixf:
			_text << "matrixf";
			break;
		case BUniform::Type_Matrixd:
			_text << "matrixd";
			break;
		default:
			_text << "none";
			break;
		}
		return _text;
	}
	inline const BString& stringOfShaderType(BShader::Type type)
	{
		_text.reset();
		switch (type)
		{
		case BShader::Type_Vertex:
			_text << "vertex";
			break;
		case BShader::Type_Fragment:
			_text << "fragment";
			break;
		default:
			_text << "none";
			break;
		}
		return _text;
	}
	inline const BString& stringOfSyntax(Syntax syntax)
	{
		_text.reset();
		switch (syntax)
		{
		case Syntax_None:			_text << "none";		break;
		case Syntax_Note:			_text << "note";		break;
		case Syntax_Include:		_text << "include";		break;
		case Syntax_File:			_text << "file";		break;
		case Syntax_Begin:			_text << "begin";		break;
		case Syntax_End:			_text << "end";			break;
		case Syntax_Decl:			_text << "decl";		break;
		case Syntax_Type:			_text << "type";		break;
		case Syntax_Value:			_text << "value";		break;
		case Syntax_Name:			_text << "name";		break;
		case Syntax_Self:			_text << "self";		break;
		case Syntax_Opera:			_text << "opera";		break;
		case Syntax_Call:			_text << "call";		break;
		case Syntax_Continue:		_text << "continue";	break;
		case Syntax_Break:			_text << "break";		break;
		case Syntax_Return:			_text << "return";		break;
		case Syntax_If:				_text << "if";			break;
		case Syntax_Else:			_text << "else";		break;
		case Syntax_For:			_text << "for";			break;
		case Syntax_While:			_text << "while";		break;
		case Syntax_Switch:			_text << "switch";		break;
		case Syntax_Case:			_text << "case";		break;
		case Syntax_Default:		_text << "default";		break;
		case Syntax_Function:		_text << "function";	break;
		case Syntax_Method:			_text << "method";		break;
		case Syntax_Class:			_text << "class";		break;
		case Syntax_Public:			_text << "public";		break;
		case Syntax_Protected:		_text << "protected";	break;
		case Syntax_Private:		_text << "private";		break;
		}
		return _text;
	}
	inline const BString& stringOfValue(const BValue& value)
	{
		_text.reset();
		if (value.is<char>())
		{
			char c = value;
			_text << (int)c << 'c';
		}
		else if (value.is<unsigned char>())
		{
			unsigned char b = value;
			_text << (int)b << 'b';
		}
		else if (value.is<short>())
		{
			short s = value;
			_text << (int)s << 's';
		}
		else if (value.is<unsigned short>())
		{
			unsigned short us = value;
			_text << (int)us << "us";
		}
		else if (value.is<int>())
		{
			int i = value;
			_text << i;
		}
		else if (value.is<unsigned int>())
		{
			unsigned int ui = value;
			_text << ui << 'u';
		}
		else if (value.is<long long>())
		{
			long long l = value;
			_text << l << "l";
		}
		else if (value.is<unsigned long long>())
		{
			unsigned long long ul = value;
			_text << ul << "ul";
		}
		else if (value.is<float>())
		{
			float f = value;
			_text << f << 'f';
		}
		else if (value.is<double>())
		{
			double d = value;
			_text << d;
		}
		else if (value.is<BString>())
		{
			const BString& str = value;
			_text << '\"' << str << '\"';
		}
		return _text;
	}

	inline BString& message() const
	{
		if (_message.empty())
		{
			_message = new BString();
		}
		BString& text = _message;
		text.reset();
		return text;
	}

	inline BVector stringToVector(const BString& str)
	{
		int pos = 0;
		int end = str.find(',', pos);
		str.substr(_text, pos, end);
		float x = _text.toFloat();
		pos = end + 1;

		end = str.find(',', pos);
		str.substr(_text, pos, end);
		float y = _text.toFloat();
		pos = end + 1;

		end = str.find(',', pos);
		str.substr(_text, pos, end);
		float z = _text.toFloat();
		pos = end + 1;

		return BVector(x, y, z);
	}
	inline BQuater stringToQuater(const BString& str)
	{
		BQuater quater;
		int pos = 0;
		int end = str.find(',', pos);
		str.substr(_text, pos, end);
		quater.x() = _text.toReal();
		pos = end + 1;

		end = str.find(',', pos);
		str.substr(_text, pos, end);
		quater.y() = _text.toReal();
		pos = end + 1;

		end = str.find(',', pos);
		str.substr(_text, pos, end);
		quater.z() = _text.toReal();
		pos = end + 1;

		end = str.find(',', pos);
		str.substr(_text, pos, end);
		quater.w() = _text.toReal();
		pos = end + 1;

		return quater;
	}
	inline BColor stringToColor(const BString& str)
	{
		int pos = 0;
		int end = str.find(',', pos);
		str.substr(_text, pos, end);
		BByte r = _text.toInt();
		pos = end + 1;

		end = str.find(',', pos);
		str.substr(_text, pos, end);
		BByte g = _text.toInt();
		pos = end + 1;

		end = str.find(',', pos);
		str.substr(_text, pos, end);
		BByte b = _text.toInt();
		pos = end + 1;

		end = str.find(',', pos);
		str.substr(_text, pos, end);
		BByte a = _text.toInt();
		pos = end + 1;

		return BColor(r, g, b, a);
	}
	inline BSize stringToSize(const BString& str)
	{
		int pos = 0;
		int end = str.find(',', pos);
		str.substr(_text, pos, end);
		int width = _text.toInt();
		pos = end + 1;

		end = str.find(',', pos);
		str.substr(_text, pos, end);
		int height = _text.toInt();
		pos = end + 1;

		return BSize(width, height);
	}
	inline BRealSize stringToRealSize(const BString& str)
	{
		int pos = 0;
		int end = str.find(',', pos);
		str.substr(_text, pos, end);
		BReal width = _text.toReal();
		pos = end + 1;

		end = str.find(',', pos);
		str.substr(_text, pos, end);
		BReal height = _text.toReal();
		pos = end + 1;

		return BRealSize(width, height);
	}
	inline BQuad stringToQuad(const BString& str)
	{
		BQuad quad;
		BStringList words;
		if (4 == str.split(words, ','))
		{
			quad.a() = stringToVector(words[0]);
			quad.b() = stringToVector(words[1]);
			quad.c() = stringToVector(words[2]);
			quad.d() = stringToVector(words[3]);
		}
		return quad;
	}
	inline BFont* stringToFont(const BString& str)
	{
		BString _text;
		int split = str.find(',');
		str.substr(_text, 0, split);
		BFont* font = new BFont(_text);
		if (split < str.size())
		{
			str.substr(_text, split + 1);
			font->setSize(_text.toInt());
		}
		return font;
	}
	inline Align stringToAlign(const BString& str)
	{
		int align = Align_None;
		BString word;
		int pos = 0;
		while (pos < str.size())
		{
			pos = str.word(word, pos);
			if (word == "center")
				align |= Align_Center;
			else if (word == "hcenter")
				align |= Align_HCenter;
			else if (word == "vcenter")
				align |= Align_VCenter;
			else if (word == "left")
				align |= Align_Left;
			else if (word == "right")
				align |= Align_Right;
			else if (word == "top")
				align |= Align_Top;
			else if (word == "bottom")
				align |= Align_Bottom;
			else if (word == ',')
				continue;
			break;
		}
		return (Align)align;
	}
	inline Format stringToFormat(const BString& str)
	{
		if (str == "char")
			return Format_Char;
		if (str == "uchar")
			return Format_UChar;
		if (str == "short")
			return Format_Short;
		if (str == "ushort")
			return Format_UShort;
		if (str == "int")
			return Format_Int;
		if (str == "uint")
			return Format_UInt;
		if (str == "float")
			return Format_Float;
		if (str == "double")
			return Format_Double;
		if (str == "rgb")
			return Format_RGB;
		if (str == "rgba")
			return Format_RGBA;
		if (str == "gray")
			return Format_Gray;
		if (str == "gray-alpha")
			return Format_Gray_Alpha;
		if (str == "alpha")
			return Format_Alpha;
		if (str == "compressed-rgb")
			return Format_Compressed_RGB;
		if (str == "compressed-rgba")
			return Format_Compressed_RGBA;
		if (str == "compressed-gray")
			return Format_Compressed_Gray;
		if (str == "compressed-gray-alpha")
			return Format_Compressed_Gray_Alpha;
		if (str == "compressed-alpha")
			return Format_Compressed_Alpha;
		return Format_None;
	}
	inline Primitive stringToPrimitive(const BString& str)
	{
		if (str == "points")
			return Primitive_Points;
		if (str == "lines")
			return Primitive_Lines;
		if (str == "lineStrip")
			return Primitive_LineStrip;
		if (str == "lineLoop")
			return Primitive_LineLoop;
		if (str == "triangles")
			return Primitive_Triangles;
		if (str == "triangleStrip")
			return Primitive_TriangleStrip;
		if (str == "triangleFan")
			return Primitive_TriangleFan;
		if (str == "quads")
			return Primitive_Quads;
		if (str == "quadStrip")
			return Primitive_QuadStrip;
		if (str == "polygon")
			return Primitive_Polygon;
		return Primitive_None;
	}
	inline BTexture::Blend stringToBlend(const BString& str)
	{
		if (str == "modulate")
			return BTexture::Blend_Modulate;
		if (str == "replace")
			return BTexture::Blend_Replace;
		if (str == "decal")
			return BTexture::Blend_Decal;
		if (str == "color")
			return BTexture::Blend_Color;
		return BTexture::Blend_None;
	}
	inline BTexture::Wrap stringToWrap(const BString& str)
	{
		if (str == "clamp")
			return BTexture::Wrap_Clamp;
		if (str == "repeat")
			return BTexture::Wrap_Repeat;
		return BTexture::Wrap_None;
	}
	inline BTexture::Filter stringToFilter(const BString& str)
	{
		if (str == "nearest")
			return BTexture::Filter_Nearest;
		if (str == "linear")
			return BTexture::Filter_Linear;
		return BTexture::Filter_None;
	}
	inline BShader::Type stringToShaderType(const BString& str)
	{
		if (str == "vertex")
			return BShader::Type_Vertex;
		if (str == "fragment")
			return BShader::Type_Fragment;
		return BShader::Type_None;
	}
	inline BUniform::Type stringToUniformType(const BString& str)
	{
		if (str == "int")
			return BUniform::Type_Int;
		if (str == "uint")
			return BUniform::Type_UInt;
		if (str == "float")
			return BUniform::Type_Float;
		if (str == "double")
			return BUniform::Type_Double;
		if (str == "vec3f")
			return BUniform::Type_Vec3f;
		if (str == "vec4f")
			return BUniform::Type_Vec4f;
		if (str == "vec3d")
			return BUniform::Type_Vec3d;
		if (str == "vec4d")
			return BUniform::Type_Vec4d;
		if (str == "matrixf")
			return BUniform::Type_Matrixf;
		if (str == "matrixd")
			return BUniform::Type_Matrixd;
		return BUniform::Type_None;
	}
	inline Syntax stringToSyntax(const BString& str)
	{
		if (str == "none")
			return Syntax_None;
		if (str == "note")
			return Syntax_Note;
		if (str == "include")
			return Syntax_Include;
		if (str == "file")
			return Syntax_File;
		if (str == "begin")
			return Syntax_Begin;
		if (str == "end")
			return Syntax_End;
		if (str == "decl")
			return Syntax_Decl;
		if (str == "type")
			return Syntax_Type;
		if (str == "value")
			return Syntax_Value;
		if (str == "name")
			return Syntax_Name;
		if (str == "self")
			return Syntax_Self;
		if (str == "opera")
			return Syntax_Opera;
		if (str == "call")
			return Syntax_Call;
		if (str == "continue")
			return Syntax_Continue;
		if (str == "break")
			return Syntax_Break;
		if (str == "return")
			return Syntax_Return;
		if (str == "if")
			return Syntax_If;
		if (str == "else")
			return Syntax_Else;
		if (str == "for")
			return Syntax_For;
		if (str == "while")
			return Syntax_While;
		if (str == "switch")
			return Syntax_Switch;
		if (str == "case")
			return Syntax_Case;
		if (str == "default")
			return Syntax_Default;
		if (str == "function")
			return Syntax_Function;
		if (str == "method")
			return Syntax_Method;
		if (str == "class")
			return Syntax_Class;
		if (str == "public")
			return Syntax_Public;
		if (str == "protected")
			return Syntax_Protected;
		if (str == "private")
			return Syntax_Private;
		return Syntax_Max;
	}
	inline BValue stringToValue(const BString& str)
	{
		BValue value;
		if (str.beginWith('\"'))
		{
			value = str;
			BString& text = value;
			text.remove(0);
			text -= '\"';
		}
		else if (str == "true")
		{
			value = true;
		}
		else if (str == "false")
		{
			value = false;
		}
		else if (str.isNumber())
		{
			if (str.contain('.'))
			{
				if (str.endWith('f'))
				{
					float v = str.toFloat();
					value = v;
				}
				else
				{
					double v = str.toDouble();
					value = v;
				}
			}
			else
			{
				if (str.endWith("ul"))
				{
					unsigned long long v = str.toLong();
					value = v;
				}
				else if (str.endWith('l'))
				{
					long long v = str.toLong();
					value = v;
				}
				else
				{
					int v = str.toInt();
					value = v;
				}
			}
		}
		return value;
	}

protected:
	typedef bool (OscDocument::* readFunc)(const BSonNode* node, BObject* object);
	typedef bool (OscDocument::* writeFunc)(BSonNode* node, const BObject* object) const;
	BMap<BString, readFunc>		_readFuncMap;
	BMap<BString, writeFunc>	_writeFuncMap;

	BSonDocument				_sondoc;
	BString						_text;
	mutable BValue				_message;
	mutable BMap<int, BObject*>		_readObjectMap;
	mutable BMap<const BObject*, int>	_writeObjectMap;

};

#endif